package managers.messengerManager;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;

import utils.ManagingMessage;
import utils.StackTracePrinter;

public class UDPProtocol implements BroadcastProtocol, SingleProtocol {

	private boolean initialized = false;
	
	private MulticastSocket mcSocket;
	private DatagramSocket socket;
	private InetAddress groupAddress;
	private int groupPort;

	public UDPProtocol (String groupIp, int groupPort) throws IOException {

		this.groupPort = groupPort;
		groupAddress = InetAddress.getByName(groupIp);

	}


	public void send(ManagingMessage managingMessage, InetAddress ip, int port) throws IOException {

		managingMessage.putProperty("senderIpAddress", InetAddress.getLocalHost());
		managingMessage.putProperty("senderPort", socket.getLocalPort());

		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(baos);
		oos.writeObject(managingMessage);	
		oos.close();
		byte[] buff = baos.toByteArray();
		DatagramPacket packet = new DatagramPacket(buff, buff.length, ip, port);
		socket.send(packet);
	}


	public ManagingMessage receive() throws IOException, ClassNotFoundException {

		Object message = null;
		byte[] buff = new byte[2000];
		DatagramPacket packet = new DatagramPacket(buff, buff.length);
		ObjectInputStream ois;

		socket.receive((DatagramPacket) packet);
		ois = new ObjectInputStream(new ByteArrayInputStream(packet.getData()));
		message = ois.readObject();
		ois.close();

		return (ManagingMessage) message;
	}

	public void broadcastSend (Object obj) {

	}

	public ManagingMessage broadcastReceive() throws IOException, ClassNotFoundException {
		Object message = null;
		byte[] buff = new byte[1000];
		DatagramPacket packet = new DatagramPacket(buff, buff.length);
		ObjectInputStream ois;

		mcSocket.receive((DatagramPacket) packet);
		ois = new ObjectInputStream(new ByteArrayInputStream(packet.getData()));
		message = ois.readObject();
		ois.close();

		return (ManagingMessage) message;


	}


	@Override
	public InetAddress getAddress() {
		return socket.getInetAddress();
	}

	@Override
	public int getPort() {
		return socket.getPort();
	}


	@Override
	public void broadcastSend(ManagingMessage managingMessage) throws Exception {

	}


	@Override
	public void writeInfo() {

	}


	@Override
	public void closeSockets() {
		try {
			socket.close();
			mcSocket.leaveGroup(groupAddress);
			mcSocket.close();
		}  catch (IOException e) {
			StackTracePrinter.print(e);
		}
	}


	@Override
	public void initialize() throws Exception {
		
		if (initialized == false) {
			socket = new DatagramSocket();
			mcSocket = new MulticastSocket(groupPort);
			mcSocket.joinGroup(groupAddress);
			
			initialized = true;
		}

	}


	@Override
	public InetAddress getBroadcastAddress() {
		return groupAddress;
	}


	@Override
	public int getBroadcastPort() {
		return groupPort;
	}



}
